<template>
  <el-dialog :title="mode === 'add' ? $t('course.addContent') : $t('course.editContent')" v-model="dialogVisible"
    width="650px" :close-on-click-modal="false">
    <el-form ref="formRef" :model="formData" :rules="rules" label-width="100px" class="min-h-[250px]">
      <el-form-item :label="$t('course.contentName')" prop="name">
        <el-input v-model="formData.name" :placeholder="$t('common.inputPhTxt', [$t('course.contentName')])"
          class="w-[300px]" maxlength="50" />
      </el-form-item>
      <el-form-item :label="$t('course.contentType')" prop="contentType">
        <el-radio-group v-model="formData.contentType">
          <el-radio class="font-normal" v-for="item in CONTENT_TYPE_CONFIG" :key="item.value" :value="item.value" :disabled="item.disabled">
            {{ $t(item.label) }}
          </el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item :label="$t('course.courseFile')" prop="files">
        <div class="flex items-center">
          <!-- 隐藏的文件上传组件 -->
          <el-upload ref="uploadRef" class="hidden-upload" :accept="getAcceptFileTypes"
            v-model:file-list="formData.files" action="#" :http-request="handleUpload" :on-remove="removeFile"
            :before-upload="beforeUpload" :auto-upload="true" :limit="1" :show-file-list="false" style="display: none;">
          </el-upload>
          <!-- 自定义按钮 -->
          <el-button @click="handleSelectFile" :icon="Plus">{{ getSelectButtonText }}</el-button>
          <div class="text-xs text-gray-500 ml-2">
            {{ getFileFormatTip }}
          </div>
        </div>
        <!-- 上传进度显示 -->
        <div v-if="isUploading || vodUploadStatus.isUploading" class="mt-3 w-full">
          <div class="flex items-center justify-between mb-2">
            <span class="text-sm text-gray-600">{{ getUploadingText }}</span>
            <div class="flex items-center space-x-2">
              <span class="text-sm text-blue-600">{{ getUploadProgressText }}</span>
              <el-button size="small" type="danger" @click="cancelUpload">
                {{ $t('common.cancelTxt') }}
              </el-button>
            </div>
          </div>
          <el-progress :percentage="getCurrentUploadProgress" :show-text="false" />
          <!-- VOD上传额外信息 -->
          <div v-if="vodUploadStatus.isUploading && vodUploadStatus.message" class="mt-2">
            <span class="text-xs text-gray-500">{{ vodUploadStatus.message }}</span>
            <span v-if="vodUploadStatus.totalChunks > 0" class="text-xs text-gray-500 ml-2">
              ({{ vodUploadStatus.currentChunk }}/{{ vodUploadStatus.totalChunks }})
            </span>
          </div>
        </div>

        <!-- 自定义文件列表显示 -->
        <div v-if="formData.files.length > 0" class="mt-3 w-full">
          <div v-for="(file, index) in formData.files" :key="index" class="px-3 py-2 bg-[#F2F7FD] rounded-md w-[95%]">

            <!-- 文件信息行 -->
            <div class="flex items-center justify-between">
              <div class="flex items-center">
                <el-icon class="text-blue-500 mr-2">
                  <SquarePlay v-if="isCurrentFileVideo" />
                  <FileText v-else />
                </el-icon>
                <div class="flex flex-col">
                  <span class="text-sm text-gray-700">{{ file.name }}</span>
                  <span v-if="videoDuration" class="text-xs text-gray-500">
                    {{ $t('course.videoDuration', [videoDuration]) }}
                  </span>
                </div>
              </div>
              <el-button size="small" :icon="CircleX" link @click="removeFile(file)" />
            </div>

            <!-- 视频预览区域 -->
            <div v-if="isCurrentFileVideo" class="mt-3">
              <div class="relative bg-black rounded-md overflow-hidden" style="aspect-ratio: 16/9;">
                <video ref="videoRef" :src="videoUrl" class="w-full h-full object-contain" controls preload="metadata"
                  @play="onVideoPlay" @pause="onVideoPause" @error="onVideoError"
                  @loadedmetadata="onVideoLoadedMetadata">
                  {{ $t('course.unsupportedVideoFormat') }}
                </video>

                <!-- 播放按钮覆盖层 -->
                <div v-if="!isPlaying"
                  class="absolute inset-0 flex items-center justify-center bg-black bg-opacity-30 cursor-pointer"
                  @click="toggleVideo">
                  <el-icon class="text-white text-4xl">
                    <Play />
                  </el-icon>
                </div>
              </div>

              <!-- 视频控制按钮 -->
              <div class="flex items-center justify-center mt-2 space-x-2">
                <el-button size="small" :icon="isPlaying ? SquarePlay : Play" @click="toggleVideo">
                  {{ isPlaying ? $t('course.pauseVideo') : $t('course.playVideo') }}
                </el-button>


              </div>
            </div>
          </div>
        </div>
      </el-form-item>
    </el-form>
    <template #footer>
      <el-button @click="handleCancel">{{ $t('common.cancelTxt') }}</el-button>
      <el-button type="primary" @click="handleConfirm">{{ $t('common.submitTxt') }}</el-button>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref, reactive, watch, computed } from 'vue'
import { ElMessage } from 'element-plus'
import { FileText, Trash2, CircleX, Play, SquarePlay, Plus } from '@vben/icons'
import { $t } from '#/locales/index.js'
import { NODE_TYPE, CONTENT_TYPE, CONTENT_TYPE_CONFIG, type ContentType } from './types'
import { obsUpload, obsDelete } from "#/utils/obs"
import { useRoute } from 'vue-router'
import { safeMergeObject } from '#/utils/objectMerge'
import { cloneDeep } from '@vben/utils'
import { uploadVideoWithChunks, isVideoFile, getVideoDuration, formatDuration, calculateOptimalChunkSize, formatFileSize } from '#/utils/videoUpload'
import { useVodPlayer } from '#/hooks/useVodPlayer'

const MAX_FILE_SIZE = 10 * 1024 * 1024 // 10MB
const MAX_VIDEO_SIZE = 5 * 1024 * 1024 * 1024 // 5GB
const ALLOWED_FILE_TYPES = [
  'application/pdf',
  'application/msword',
  'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
]

const props = defineProps({
  visible: Boolean,
  mode: { type: String, default: 'add' }, // add | edit
  data: { type: Object, default: () => ({}) }
})
const emit = defineEmits(['update:visible', 'submit', 'cancel'])

// 使用计算属性控制弹窗显示
const dialogVisible = computed({
  get: () => props.visible,
  set: (value) => emit('update:visible', value)
})
const initData = {
  name: '',
  contentType: CONTENT_TYPE.DOCUMENT as ContentType,
  path: '',
  files: [] as any[],
  vodAssetId: '' // VOD媒资ID
}
const formRef = ref()
const uploadRef = ref()
const route = useRoute()
const formData = reactive(cloneDeep(initData))

// 视频相关状态
const uploadProgress = ref(0)
const isUploading = ref(false)
const videoDuration = ref('')
const videoUrl = ref('')
const isPlaying = ref(false)
const videoRef = ref()
const currentUploadController = ref<AbortController | null>(null)

// 使用VOD播放器钩子
const {
  loading: vodLoading,
  error: vodError,
  uploadStatus: vodUploadStatus,
  uploadByChunks,
  uploadDirect,
  reset: resetVod
} = useVodPlayer()

watch(() => props.visible, (val) => {
  formRef.value?.resetFields()
  if (val) {
    if (props.mode === 'edit' && props.data) {
      safeMergeObject(formData, props.data)
      if (props?.data?.path) {
        // 处理文件路径，删除第一个/前面的内容和_后面的hash
        const path = props.data.path
        const lastSlashIndex = path.lastIndexOf('/')
        if (lastSlashIndex !== -1) {
          const fileNameWithHash = path.substring(lastSlashIndex + 1)
          const underscoreIndex = fileNameWithHash.lastIndexOf('_')
          if (underscoreIndex !== -1) {
            const originalFileName = fileNameWithHash.substring(0, underscoreIndex)
            formData.files = [{ name: originalFileName }]
          } else {
            formData.files = [{ name: fileNameWithHash }]
          }
        } else {
          formData.files = [{ name: path }]
        }
      }
    } else {
      // 新增模式，重置数据
      safeMergeObject(formData, initData)
    }
  } else {
    // 弹窗关闭时清理视频相关状态
    cleanupVideoResources()
    uploadProgress.value = 0
    isUploading.value = false
  }
})

const rules = {
  name: [
    { required: true, message: $t('common.inputPhTxt', [$t('course.contentName')]), trigger: 'blur' }
  ],
  contentType: [
    { required: true, message: $t('common.requiredTxt', [$t('course.contentType')]), trigger: 'change' }
  ],
  files: [
    { required: true, message: $t('common.selectPhTxt', [$t('course.courseFile')]), trigger: 'change' }
  ]
}

const beforeUpload = async (file: File) => {
  // 检查是否已经有文件
  if (formData.files.length > 0) {
    ElMessage.error($t('course.deleteFileTip'))
    return false
  }

  // 根据内容类型获取允许的文件类型
  let allowedTypes: string[] = []
  let allowedExtensions: RegExp

  switch (formData.contentType) {
    case CONTENT_TYPE.VIDEO:
      allowedTypes = [
        'video/mp4', 'video/wmv', 'video/avi', 'video/mov',
        'video/flv', 'video/rmvb', 'video/3gp', 'video/m4v', 'video/mkv'
      ]
      allowedExtensions = /\.(mp4|wmv|avi|mov|flv|rmvb|3gp|m4v|mkv)$/i
      break
    case CONTENT_TYPE.DOCUMENT:
      allowedTypes = [
        'application/vnd.openxmlformats-officedocument.presentationml.presentation', // pptx
        'application/vnd.ms-powerpoint', // ppt
        'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // docx
        'application/msword', // doc
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // xlsx
        'application/vnd.ms-excel', // xls
        'application/pdf' // pdf
      ]
      allowedExtensions = /\.(pptx|ppt|docx|doc|xlsx|xls|pdf)$/i
      break
    case CONTENT_TYPE.ARTICLE:
      allowedTypes = [
        'image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp'
      ]
      allowedExtensions = /\.(jpg|jpeg|png|gif|webp)$/i
      break
    default:
      allowedTypes = [
        'application/vnd.openxmlformats-officedocument.presentationml.presentation',
        'application/vnd.ms-powerpoint',
        'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        'application/msword',
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        'application/vnd.ms-excel',
        'application/pdf',
        'video/mp4', 'video/wmv', 'video/avi', 'video/mov',
        'video/flv', 'video/rmvb', 'video/3gp', 'video/m4v', 'video/mkv'
      ]
      allowedExtensions = /\.(pptx|ppt|docx|doc|xlsx|xls|pdf|mp4|wmv|avi|mov|flv|rmvb|3gp|m4v|mkv)$/i
  }

  // 检查文件类型
  const isVideo = isVideoFile(file)
  const isAllowedType = allowedTypes.includes(file.type) || allowedExtensions.test(file.name)

  if (!isAllowedType) {
    ElMessage.error($t('course.fileTypeError'))
    return false
  }

  // 检查文件大小
  let maxSize: number
  let sizeErrorKey: string

  switch (formData.contentType) {
    case CONTENT_TYPE.VIDEO:
      maxSize = MAX_VIDEO_SIZE
      sizeErrorKey = 'course.videoSizeLimit'
      break
    case CONTENT_TYPE.DOCUMENT:
      maxSize = MAX_FILE_SIZE
      sizeErrorKey = 'course.fileSizeError'
      break
    case CONTENT_TYPE.ARTICLE:
      maxSize = MAX_FILE_SIZE // 图片也用10MB限制
      sizeErrorKey = 'course.fileSizeError'
      break
    default:
      maxSize = isVideo ? MAX_VIDEO_SIZE : MAX_FILE_SIZE
      sizeErrorKey = isVideo ? 'course.videoSizeLimit' : 'course.fileSizeError'
  }

  if (file.size > maxSize) {
    ElMessage.error($t(sizeErrorKey))
    return false
  }

  // 如果是视频文件，获取时长信息
  if (isVideo) {
    try {
      const duration = await getVideoDuration(file)
      videoDuration.value = formatDuration(duration)
      videoUrl.value = URL.createObjectURL(file)
    } catch (error) {
      console.warn('无法获取视频时长:', error)
    }
  }

  return true
}

const handleUpload = async (options: any) => {
  const { file } = options
  const isVideo = isVideoFile(file)

  if (isVideo) {
    // 视频文件使用VOD上传
    isUploading.value = true
    uploadProgress.value = 0

    console.log(`开始上传视频文件到VOD: ${file.name}, 大小: ${formatFileSize(file.size)}`)

    try {
      // 准备VOD上传参数
      const uploadParams = {
        file,
        title: formData.name || file.name.replace(/\.[^/.]+$/, ''), // 使用内容名称或文件名作为标题
        description: `课程内容: ${formData.name}`,
        autoPublish: true,
        chunkSize: file.size > 100 * 1024 * 1024 ? 20 * 1024 * 1024 : 10 * 1024 * 1024, // 大文件使用20MB分片
        onProgress: (progress: any) => {
          uploadProgress.value = progress.percentage
          console.log('VOD上传进度:', progress)
        }
      }

      let assetId: string
      
      // 根据文件大小选择上传方式
      if (file.size <= 20 * 1024 * 1024) {
        // 小于20MB使用直接上传
        console.log('使用VOD直接上传')
        const result = await uploadDirect(uploadParams)
        assetId = result.assetId
      } else {
        // 大于20MB使用分段上传
        console.log('使用VOD分段上传')
        assetId = await uploadByChunks(uploadParams)
      }

      // 上传成功
      if (formRef.value && formRef.value.clearValidate) {
        formRef.value.clearValidate('files')
      }
      
      // 保存VOD媒资ID而不是文件路径
      formData.vodAssetId = assetId
      formData.path = `vod://${assetId}` // 使用特殊格式标识这是VOD资源
      
      isUploading.value = false
      uploadProgress.value = 100
      ElMessage.success(getUploadSuccessText.value)
      console.log('VOD上传完成，媒资ID:', assetId)
      
    } catch (error) {
      console.error('VOD上传失败:', error)
      isUploading.value = false
      uploadProgress.value = 0

      let errorMessage = getUploadFailedText.value
      if (error instanceof Error) {
        if (error.message?.includes('已取消')) {
          return // 上传被取消，不显示错误信息
        } else if (error.message?.includes('Token')) {
          errorMessage = 'VOD服务认证失败，请联系管理员'
        } else if (error.message?.includes('网络')) {
          errorMessage = '网络连接失败，请检查网络后重试'
        }
      }

      ElMessage.error(errorMessage)
    }
  } else {
    // 普通文件使用原有上传方式
    obsUpload({
      Key: file.name,
      SourceFile: file
    }, (err: any, result: any, path?: string) => {
      if (err) {
        ElMessage.error(getUploadFailedText.value)
        return
      }
      // 重置 files 字段的校验（避免上传后校验状态不更新）
      if (formRef.value && formRef.value.clearValidate) {
        formRef.value.clearValidate('files')
      }
      formData.path = path || ''
      ElMessage.success(getUploadSuccessText.value)
    })
  }
}

const removeFile = (file: any) => {
  // 这样可以避免校验失败时误删除服务器文件
  if (formData.path) {
    obsDelete({
      Key: formData.path
    }, (err: any, result: any) => {
      if (err) {
        ElMessage.error($t('course.fileDeleteFailed'))
        return
      }
      // 重置 files 字段的校验（避免上传后校验状态不更新）
      if (formRef.value && formRef.value.clearValidate) {
        formRef.value.clearValidate('files')
      }
      // 清空路径
      formData.path = ''
      ElMessage.success($t('course.fileDeleteSuccess'))
    })
  }

  // 清理视频相关状态
  cleanupVideoResources()

  // 清空文件列表（无论是否有服务器文件）
  formData.files = []
}

const handleSelectFile = () => {
  // 检查是否已经有文件
  if (formData.files.length > 0) {
    ElMessage.error($t('course.deleteFileTip'))
    return
  }

  // 手动触发文件选择器
  if (uploadRef.value) {
    // 获取 el-upload 组件内部的 input 元素并触发点击
    const inputElement = uploadRef.value.$el.querySelector('input[type="file"]')
    if (inputElement) {
      inputElement.click()
    }
  }
}

// 视频播放控制
const toggleVideo = async () => {
  const videoElement = getVideoElement()

  if (!videoElement) {
    return
  }

  try {
    if (isPlaying.value) {
      videoElement.pause()
      isPlaying.value = false
    } else {
      await videoElement.play()
      isPlaying.value = true
    }
  } catch (error) {
    console.error('视频播放失败:', error)
    ElMessage.error('视频播放失败，请检查视频文件是否有效')
    isPlaying.value = false
  }
}

const onVideoPlay = () => {
  isPlaying.value = true
}

const onVideoPause = () => {
  isPlaying.value = false
}

const onVideoError = (event: Event) => {
  console.error('视频加载或播放出错:', event)
  isPlaying.value = false
  ElMessage.error('视频加载失败，请检查视频文件格式')
}

const onVideoLoadedMetadata = () => {
  // 视频元数据加载完成
}

// 获取实际的video元素的工具函数
const getVideoElement = (): HTMLVideoElement | null => {
  const element = videoRef.value?.[0] || videoRef.value
  return element instanceof HTMLVideoElement ? element : null
}



// 清理视频资源
const cleanupVideoResources = () => {
  const videoElement = getVideoElement()

  if (videoElement) {
    videoElement.pause()
    videoElement.currentTime = 0
  }

  if (videoUrl.value) {
    URL.revokeObjectURL(videoUrl.value)
    videoUrl.value = ''
  }

  isPlaying.value = false
  videoDuration.value = ''

  // 取消正在进行的上传
  if (currentUploadController.value) {
    currentUploadController.value.abort()
    currentUploadController.value = null
  }
  
  // 重置VOD状态
  resetVod()
}

// 检查是否为视频文件
const isCurrentFileVideo = computed(() => {
  return formData.files.length > 0 && videoUrl.value
})

// 根据内容类型获取相应的文本
const getSelectButtonText = computed(() => {
  switch (formData.contentType) {
    case CONTENT_TYPE.VIDEO:
      return $t('course.selectVideo')
    case CONTENT_TYPE.DOCUMENT:
      return $t('course.selectDocument')
    case CONTENT_TYPE.ARTICLE:
      return $t('course.selectArticle')
    default:
      return $t('course.selectFile')
  }
})

const getFileFormatTip = computed(() => {
  switch (formData.contentType) {
    case CONTENT_TYPE.VIDEO:
      return $t('course.videoFileFormatTip')
    case CONTENT_TYPE.DOCUMENT:
      return $t('course.documentFileFormatTip')
    case CONTENT_TYPE.ARTICLE:
      return $t('course.articleFileFormatTip')
    default:
      return $t('course.fileFormatTip')
  }
})

const getUploadingText = computed(() => {
  switch (formData.contentType) {
    case CONTENT_TYPE.VIDEO:
      return $t('course.videoUploading')
    case CONTENT_TYPE.DOCUMENT:
      return $t('course.documentUploading')
    case CONTENT_TYPE.ARTICLE:
      return $t('course.articleUploading')
    default:
      return $t('course.videoUploading')
  }
})

const getUploadProgressText = computed(() => {
  switch (formData.contentType) {
    case CONTENT_TYPE.VIDEO:
      return $t('course.videoUploadProgress', [uploadProgress.value])
    case CONTENT_TYPE.DOCUMENT:
      return $t('course.documentUploadProgress', [uploadProgress.value])
    case CONTENT_TYPE.ARTICLE:
      return $t('course.articleUploadProgress', [uploadProgress.value])
    default:
      return $t('course.videoUploadProgress', [uploadProgress.value])
  }
})

const getUploadSuccessText = computed(() => {
  switch (formData.contentType) {
    case CONTENT_TYPE.VIDEO:
      return $t('course.videoUploadSuccess')
    case CONTENT_TYPE.DOCUMENT:
      return $t('course.documentUploadSuccess')
    case CONTENT_TYPE.ARTICLE:
      return $t('course.articleUploadSuccess')
    default:
      return $t('course.videoUploadSuccess')
  }
})

const getUploadFailedText = computed(() => {
  switch (formData.contentType) {
    case CONTENT_TYPE.VIDEO:
      return $t('course.videoUploadFailed')
    case CONTENT_TYPE.DOCUMENT:
      return $t('course.documentUploadFailed')
    case CONTENT_TYPE.ARTICLE:
      return $t('course.articleUploadFailed')
    default:
      return $t('course.videoUploadFailed')
  }
})

const getAcceptFileTypes = computed(() => {
  switch (formData.contentType) {
    case CONTENT_TYPE.VIDEO:
      return '.mp4,.wmv,.avi,.mov,.flv,.rmvb,.3gp,.m4v,.mkv'
    case CONTENT_TYPE.DOCUMENT:
      return '.pptx,.ppt,.docx,.doc,.xlsx,.xls,.pdf'
    case CONTENT_TYPE.ARTICLE:
      return '.jpg,.jpeg,.png,.gif,.webp'
    default:
      return '.pptx,.ppt,.docx,.doc,.xlsx,.xls,.pdf,.mp4,.wmv,.avi,.mov,.flv,.rmvb,.3gp,.m4v,.mkv'
  }
})

// 取消上传
const cancelUpload = () => {
  if (currentUploadController.value) {
    currentUploadController.value.abort()
    currentUploadController.value = null
  }
  isUploading.value = false
  uploadProgress.value = 0
  resetVod() // 重置VOD状态
  ElMessage.info('上传已取消')
}

// 获取当前上传进度
const getCurrentUploadProgress = computed(() => {
  if (vodUploadStatus.isUploading) {
    return vodUploadStatus.progress
  }
  return uploadProgress.value
})

async function handleConfirm() {
  try {
    await formRef.value.validate()
    
    // 构建提交数据
    const submitData: any = {
      name: formData.name,
      contentType: formData.contentType,
      path: formData.path,
      type: NODE_TYPE.FILE
    }
    
    // 如果是视频且有VOD媒资ID，则添加到提交数据中
    if (formData.contentType === CONTENT_TYPE.VIDEO && formData.vodAssetId) {
      submitData.vodAssetId = formData.vodAssetId
    }
    
    emit('submit', submitData)
    emit('update:visible', false)
    formRef.value.resetFields()
  } catch (error) {
  }
}

defineExpose({
  getData: () => formData
})

function handleCancel() {
  // 清理视频相关状态
  cleanupVideoResources()
  uploadProgress.value = 0
  isUploading.value = false

  emit('cancel')
  emit('update:visible', false)
}
</script>

<style scoped>
.upload-demo {
  display: inline-block;
}

.hidden-upload {
  display: none !important;
  visibility: hidden !important;
  pointer-events: none !important;
  position: absolute !important;
  left: -9999px !important;
}
</style>
